package com.supermali.entity.npc.person;

import com.supermali.behavior.Gravity;
import com.supermali.behavior.down.DownBehavior;
import com.supermali.behavior.down.land.LandPersonDown;
import com.supermali.behavior.forward.MoveForwordBehavior;
import com.supermali.behavior.forward.land.LandPersonMoveForword;
import com.supermali.behavior.glide.DefaultGlideBehavior;
import com.supermali.behavior.glide.GlideBehavior;
import com.supermali.behavior.goback.GobackBehavior;
import com.supermali.behavior.goback.land.LandPersonGoBack;
import com.supermali.behavior.jump.JumpBehavior;
import com.supermali.behavior.jump.land.LandPersonJump;
import com.supermali.behavior.squatDown.SquatDownBehavior;
import com.supermali.behavior.squatDown.land.LandPersonSquat;
import com.supermali.behavior.terminate.TerminateBehavior;
import com.supermali.behavior.terminate.land.LandTerminate;
import com.supermali.creater.GameStarter;
import com.supermali.creater.MapCreater;
import com.supermali.creater.img.ImgHelper;
import com.supermali.creater.img.ImgKey;
import com.supermali.creater.img.ImgLoader;
import com.supermali.entity.MapImageAbstract;
import com.supermali.entity.map.hinder.HinderMapAbstract;
import com.supermali.entity.npc.IntesectDirect;
import com.supermali.entity.npc.NPCAbstract;
import com.supermali.entity.npc.bullet.Bullet;
import com.supermali.entity.npc.bullet.BulletAbstract;
import com.supermali.entity.npc.finish.FinishAbstract;
import com.supermali.entity.npc.finish.HouseFinish;
import com.supermali.entity.npc.monistor.MonistorAbstract;
import com.supermali.entity.npc.monistor.helpful.HelpfulAbstract;
import com.supermali.entity.npc.monistor.hurt.HurtAbstract;
import com.supermali.util.ImgChangeRate;
import com.supermali.util.ImgConvertUtil;

import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @project super-mali
 * @Date 2021/2/28
 * @Auth yangrui
 **/
public class Person extends NPCAbstract {

    private List<? extends MapImageAbstract> hinders;

    //1秒钟才能点击一次发送炮弹
    private int BULLET_SPACE = 1000;
    private long lastMillis;

    // 前进行为
    MoveForwordBehavior forwordBehavior;
    // 后退行为
    GobackBehavior gobackBehavior;
    // 下降行为
    DownBehavior downBehavior;
    // 跳跃行为
    JumpBehavior jumpBehavior;
    // 静止行为
    TerminateBehavior terminateBehavior;
    // 下蹲行为
    SquatDownBehavior squatDownBehavior;
    // 下滑行为
    GlideBehavior glideBehavior;

    // 大、小、大的可发炮弹
    private BigStatus bigStatus;
    // 跳、前进、后退、下蹲
    private RunState runState;

    private Direct direct;

    private Gravity gravity;
    // 图片切换速率控制类
    private ImgChangeRate imgChangeRate;

    public enum Direct{
        Left,Right
    }

    public enum BigStatus{
        BIG,SMALL,BIG_BULLET
    }
    public enum RunState{
        Jump,FORWARD,GOBACK,DOWN,TERMINATE,DIED,SITDOWN,HUG
    }

    public Person(Double x, Double y, MapCreater mapCreater) {
        super(x, y, mapCreater);
    }

    public void setBigStatus(BigStatus bigStatus) {
        this.bigStatus = bigStatus;
    }

    public void setRunState(RunState runState) {
        this.runState = runState;
    }

    @Override
    public void make(Graphics g) {
        super.make(g);
//        g.drawString("用户坐标：x="+this.getX()+" y="+this.getY(),70,30);
//        g.drawString("空格键开始游戏，按键Q发射炮弹，上下左右键控制人物移动", 70,30);
        /*drawLine(g,0,80,600,80);
        drawLine(g,0,64,600,64);
        drawLine(g,0,48,600,48);
        drawLine(g,0,32,600,32);
        drawLine(g,0,16,600,16);
        drawLine(g,0,0,600,0);*/
    }

    private void drawLine(Graphics g,int x0,int y0,int x1,int y1){
        Point2D.Double aDouble0 = new Point2D.Double(x0,y0);
        Point2D.Double aDouble1 = new Point2D.Double(x1,y1);
        Point2D transform0 = getWorldAffineTransform().transform(aDouble0, null);
        Point2D transform1 = getWorldAffineTransform().transform(aDouble1, null);
        g.drawLine((int)transform0.getX(),(int)transform0.getY(),(int)transform1.getX(),(int)transform1.getY());
    }

    @Override
    public Set<IntesectDirect> checkCollide() {
        Set<IntesectDirect> intesectDirects = super.checkCollide();
        // 检测结束标志
        GameStarter gameStarter = getMapCreater().getGameStarter();
        if(gameStarter.getGameStatu()== GameStarter.GameStatu.Running||gameStarter.getGameStatu()== GameStarter.GameStatu.FinishMoveback) {
            List<FinishAbstract> finishAbstracts = getMapCreater().getFinishAbstracts();
            for (FinishAbstract finishAbstract : finishAbstracts) {
                IntesectDirect direct = dealOne(finishAbstract);
                if (direct != null) {
                    intesectDirects.add(direct);
                }
            }
        }

        for(IntesectDirect direct: intesectDirects){
            if(direct.getIntesect() instanceof MonistorAbstract){
                // 碰到怪物，分情况讨论
                if(direct.getIntesect() instanceof HelpfulAbstract){
                    ((HelpfulAbstract) direct.getIntesect()).helpPerson();
                    direct.getIntesect().destroy(0);
                }else if(direct.getIntesect() instanceof HurtAbstract){
                    if(direct.getDirect()!= IntesectDirect.Direct.TOP) {
                        ((HurtAbstract) direct.getIntesect()).hurtPerson();
                    }else direct.getIntesect().destroy(0);
                }
            }else if(direct.getIntesect() instanceof FinishAbstract){
                FinishAbstract intesect = (FinishAbstract) direct.getIntesect();
                intesect.finish();
            }else if(direct.getDirect()==IntesectDirect.Direct.DOWN&&direct.getIntesect() instanceof HinderMapAbstract){
                direct.getIntesect().destroy(0);
            }
        }
        return intesectDirects;
    }

    public GlideBehavior getGlideBehavior() {
        return glideBehavior;
    }

    @Override
    public void proccessData(long delta) {
        if(!jumpBehavior.isOver()){
            jumpBehavior.jump();
        }else if(!glideBehavior.isOver()&&!glideBehavior.isFinish()){
            glideBehavior.glide(delta);
        }else {
            gravity.autoDown();
        }
        // 设置将要展示的图片
        imgChangeRate.changeIndex(delta);
        BufferedImage img = getImg();
        this.setBufferedImage(img);
    }

    public BufferedImage getImg(){
        BufferedImage bufferedImage = null;
        if(bigStatus == BigStatus.BIG){
            if(runState==RunState.GOBACK){
                bufferedImage =getImgByKey(ImgKey.BigPerson.FORWARD);
            } else if(runState==RunState.FORWARD){
                bufferedImage =getImgByKey(ImgKey.BigPerson.FORWARD);
            }else if(runState==RunState.Jump){
                bufferedImage =getImgByKey(ImgKey.BigPerson.JUMP);
            }else if(runState==RunState.DOWN){
                bufferedImage =getImgByKey(ImgKey.BigPerson.DOWN);
            }else if(runState==RunState.SITDOWN){
                bufferedImage =getImgByKey(ImgKey.BigPerson.SITDOWN);
            }else if(runState==RunState.HUG){
                bufferedImage =getImgByKey(ImgKey.BigPerson.HUG);
            }else {
                bufferedImage =getImgByKey(ImgKey.BigPerson.TERMINATE);
            }
        }else if(bigStatus == BigStatus.BIG_BULLET){
            if(runState==RunState.GOBACK){
                bufferedImage =getImgByKey(ImgKey.BigBulletPerson.FORWARD);
            } else if(runState==RunState.FORWARD){
                bufferedImage =getImgByKey(ImgKey.BigBulletPerson.FORWARD);
            }else if(runState==RunState.Jump){
                bufferedImage =getImgByKey(ImgKey.BigBulletPerson.JUMP);
            }else if(runState==RunState.DOWN){
                bufferedImage =getImgByKey(ImgKey.BigBulletPerson.DOWN);
            }else if(runState==RunState.SITDOWN){
                bufferedImage =getImgByKey(ImgKey.BigBulletPerson.SITDOWN);
            }else if(runState==RunState.HUG){
                bufferedImage =getImgByKey(ImgKey.BigBulletPerson.HUG);
            }else {
                bufferedImage =getImgByKey(ImgKey.BigBulletPerson.TERMINATE);
            }
        }else {
            if(runState==RunState.GOBACK){
                bufferedImage =getImgByKey(ImgKey.SmallPerson.FORWARD);
            } else if(runState==RunState.FORWARD){
                bufferedImage =getImgByKey(ImgKey.SmallPerson.FORWARD);
            }else if(runState==RunState.Jump){
                bufferedImage =getImgByKey(ImgKey.SmallPerson.JUMP);
            }else if(runState==RunState.DOWN){
                bufferedImage =getImgByKey(ImgKey.SmallPerson.DOWN);
            }else if(runState==RunState.SITDOWN){
                bufferedImage =getImgByKey(ImgKey.SmallPerson.SITDOWN);
            }else if(runState==RunState.HUG){
                bufferedImage =getImgByKey(ImgKey.SmallPerson.HUG);
            }else {
                bufferedImage =getImgByKey(ImgKey.SmallPerson.TERMINATE);
            }
        }
        if(isLeft()){
            bufferedImage = ImgConvertUtil.mirror(bufferedImage);
        }
        return bufferedImage;
    }

    private BufferedImage getImgByKey(Enum key){
        Map<Enum, ImgHelper> imgs = ImgLoader.getImgs();
        ImgHelper imgHelper = imgs.get(key);
        int index = imgChangeRate.getIndex();
        BufferedImage select = imgHelper.select(index);
        return select;
    }

    public boolean isLeft() {
        return direct==Direct.Left;
    }

    public void setDirect(Direct direct) {
        this.direct = direct;
    }

    public void sendBullet(long delta){
        if(this.bigStatus==BigStatus.BIG_BULLET){
            long cuTime = System.currentTimeMillis();
            if(cuTime-lastMillis>BULLET_SPACE) {
                lastMillis = cuTime;
                List<BulletAbstract> bulletAbstracts = getMapCreater().getBulletAbstracts();
                double x = this.getX();
                double y = this.getY();
                BufferedImage bufferedImage = this.getBufferedImage();
                Bullet bullet = new Bullet(x + bufferedImage.getWidth(), y + bufferedImage.getHeight() / 2, getMapCreater());
                if(direct==Direct.Left){
                    bullet.setXdirect(-1);
                    bullet.setX(x);
                }
                bulletAbstracts.add(bullet);
            }
        }
    }

    @Override
    public void init() {
        hinders = new ArrayList<>();
        forwordBehavior = new LandPersonMoveForword(this);
        gobackBehavior = new LandPersonGoBack(this);
        jumpBehavior = new LandPersonJump(this);
        downBehavior = new LandPersonDown(this);
        terminateBehavior = new LandTerminate(this);
        squatDownBehavior=new LandPersonSquat(this);
        glideBehavior=new DefaultGlideBehavior(this);
        this.direct = Direct.Right;
        gravity = new Gravity(this);
        imgChangeRate = new ImgChangeRate();
        bigStatus=BigStatus.SMALL;
        lastMillis=0;

        ImgHelper imgHelper = ImgLoader.getImgHelper(ImgKey.BigPerson.TERMINATE);
        int index = imgChangeRate.getIndex();
        BufferedImage select = imgHelper.select(index);
        this.setBufferedImage(select);

    }

    public MoveForwordBehavior getForwordBehavior() {
        return forwordBehavior;
    }

    public GobackBehavior getGobackBehavior() {
        return gobackBehavior;
    }

    public DownBehavior getDownBehavior() {
        return downBehavior;
    }

    public JumpBehavior getJumpBehavior() {
        return jumpBehavior;
    }

    public TerminateBehavior getTerminateBehavior() {
        return terminateBehavior;
    }

    public SquatDownBehavior getSquatDownBehavior() {
        return squatDownBehavior;
    }

    public BigStatus getBigStatus() {
        return bigStatus;
    }

    public Gravity getGravity() {
        return gravity;
    }
}
